package modules.java8.stream2;

import modules.dao.UserRepository;
import modules.entities.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Stream流式计算 3
 *      分组
 *      分区
 *      APi 测试
 *
 * @create 2021-03-16
 */
@SpringBootTest
public class Stream3 {
    @Autowired
    UserRepository userRepository;

    // 分组
    @Test
    void test6() {

        List<User> list = userRepository.findAll();
        list.forEach(System.out::println);

        Map<Integer, List<User>> collect = list.stream().collect(Collectors.groupingBy(User::getGender));
        System.out.println(collect);
        //多级分组
        Map<Integer, Map<String, List<User>>> collect1 = list.stream()
                .collect(Collectors.groupingBy(User::getGender,
                    Collectors.groupingBy((e) -> {
                        User user = (User) e;
                        if (user.getId() <= 4) {
                            return "一级";
                        } else if (user.getId() <= 6) {
                            return "二级";
                        } else {
                            return "三级";
                        }
                    })
                ));
        System.out.println("多级分组");
        System.out.println(collect1);
        for (Map<String, List<User>> v : collect1.values()) {
            System.out.println("value= " + v);
        }
    }


    // 分区  分为两个区（一个满足条件/不满足）
    @Test
    void test7() {

        List<User> list = userRepository.findAll();
        list.forEach(System.out::println);
        // 性别为 1 的一区，2 的另一个区
        Map<Boolean, List<User>> collect = list.stream()
                .collect(Collectors.partitioningBy((e) -> { return e.getGender() > 1; }));
        System.out.println(collect);

        for (List<User> v : collect.values()) {
            System.out.println("value= " + v);
        }

        System.out.println("通过Collectors 获取总数，平均值，最大值");
        IntSummaryStatistics obj = list.stream().collect(Collectors.summarizingInt(User::getId));

        long sum = obj.getSum();
        double average = obj.getAverage();
        int max = obj.getMax();
        System.out.println(sum);
        System.out.println(average);
        System.out.println(max);

        System.out.println("通过Collectors 连接字符串");
        String str = list.stream()
                .map(User::getUsername)
                .collect(Collectors.joining(",", "--", "--"));
        System.out.println(str);

    }

    // APi 测试
    @Test
    void test8() {
        List<User> list = userRepository.findAll();
        list.forEach(System.out::println);

        // 1.给一组数字，返回每个数的平方构成的列表 【1，2，3，4】 - 【1，4，9，16】
        Integer[] arr = new Integer[]{1, 2, 3, 4};
        List<Integer> collect = Arrays.stream(arr).map((x) -> { return x * x; }).collect(Collectors.toList());
        System.out.println(collect);

        // 2.使用map ,reduce 数一数有多少个User
        Optional<Integer> reduce = list.stream().map((e) -> { return 1; }).reduce(Integer::sum);
        System.out.println(reduce.get());

        // 3.找出性别男的全部数据，ID进行排序
        System.out.println("过滤+倒叙排序：--------------");
        list.stream().filter((e) -> { return e.getGender() == 1; })
                .sorted((x, y) -> { return -Integer.compare(x.getId(), y.getId()); })
                .forEach(System.out::println);

        // 4.找出姓名全部数据
        System.out.println("去重 --------------");
        list.stream().map(User::getUsername).distinct().forEach(System.out::println);

        // 5.有没有性别是1的数据
        System.out.println("有没有anyMatch --------------");
        boolean b = list.stream().anyMatch((x) -> { return x.getGender() == 1; });
        System.out.println(b);

        // 5.查询userType的总数
        System.out.println("总数 --------------");
        Optional<Integer> reduce1 = list.stream().filter((x) -> {
            return x.getUserType() != null;
        }).map(User::getUserType).reduce(Integer::sum);
        System.out.println(reduce1.get());

    }

}
